#include "dexgel\dexgel.hpp"

#include <vector>
#include <fstream>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#pragma comment(lib, "dexgel.lib")



dexgel::Mesh* makeCube(dexgel::Rendrer *rend)
{
	std::vector<dexgel::LitVertex> verts;
	std::vector<unsigned short> indices;

	unsigned int color = 0xffaabbcc; 

	float gCubeVerts[] =
	{
		-0.5, -0.5, -0.5, 
		-0.5, 0.5, -0.5, 
		0.5, -0.5, -0.5, 
		0.5, -0.5, -0.5, 
		-0.5, 0.5, -0.5, 
		0.5, 0.5, -0.5,  
		0.5, -0.5, -0.5, 
		0.5, 0.5, -0.5,  
		0.5, -0.5, 0.5,  
		0.5, -0.5, 0.5,  
		0.5, 0.5, -0.5,  
		0.5, 0.5, 0.5, 
		0.5, -0.5, 0.5,  
		0.5, 0.5, 0.5, 
		-0.5, -0.5, 0.5, 
		-0.5, -0.5, 0.5, 
		0.5, 0.5, 0.5, 
		-0.5, 0.5, 0.5,  
		-0.5, -0.5, 0.5, 
		-0.5, 0.5, 0.5,  
		-0.5, -0.5, -0.5,
		-0.5, -0.5, -0.5, 
		-0.5, 0.5, 0.5,  
		-0.5, 0.5, -0.5, 
		-0.5, 0.5, -0.5, 
		-0.5, 0.5, 0.5,  
		0.5, 0.5, -0.5,  
		0.5, 0.5, -0.5,  
		-0.5, 0.5, 0.5,  
		0.5, 0.5, 0.5,
		-0.5, -0.5, -0.5, 
		0.5, -0.5, -0.5, 
		-0.5, -0.5, 0.5, 
		0.5, -0.5, -0.5, 
		0.5, -0.5, 0.5,  
		-0.5, -0.5, 0.5, 
	};


	// duplicating verts...
	for(int i=0; i<36*3; i+=3*3)
	{
		glm::vec3 v1( gCubeVerts[i+0], gCubeVerts[i+1], gCubeVerts[i+2] );
		glm::vec3 v2( gCubeVerts[i+3], gCubeVerts[i+4], gCubeVerts[i+5] );
		glm::vec3 v3( gCubeVerts[i+6], gCubeVerts[i+7], gCubeVerts[i+8] );

		glm::vec3 n = glm::cross( (v2-v1), (v3-v1) );
		n = glm::normalize( n );


		dexgel::LitVertex vert1(v1, n, color);
		dexgel::LitVertex vert2(v2, n, color);
		dexgel::LitVertex vert3(v3, n, color);
		verts.push_back( vert1 );
		verts.push_back( vert2 );
		verts.push_back( vert3 );
	}
				
	return rend->createMesh( &verts[0], verts.size() );
}

int main()
{
	float xres = 600;
	float yres = 600;

	dexgel::Window App( (int)xres, (int)yres, "Lighting");
	
	dexgel::Rendrer *rend = App.getRendrer();
	glm::mat4 mCam = glm::translate( glm::mat4(1.0f), glm::vec3(0.f, 0.f, 25.f) );
	float px = 0.0f;
	float py = 0.0f;
	float pz = 25.0f;

	float hang = 0.0f;
	float vang = 0.0f;

	float oldmousx = 0.0f;
	float oldmousy = 0.0f;
	
	dexgel::Mesh *mesh = makeCube( rend );
	double time = 0.0;
	double oldtime = 0.0;
	double dt = 0.0;

	std::vector<dexgel::SVertex> verts;

	unsigned int color = 0xffaabbcc; 

	float gCubeVerts[] =
	{
		 -0.5, -0.5, -0.5, 
		 -0.5, 0.5, -0.5, 
		 0.5, -0.5, -0.5, 
		 0.5, -0.5, -0.5, 
		 -0.5, 0.5, -0.5, 
		 0.5, 0.5, -0.5,  
		 0.5, -0.5, -0.5, 
		 0.5, 0.5, -0.5,  
		 0.5, -0.5, 0.5,  
		 0.5, -0.5, 0.5,  
		 0.5, 0.5, -0.5,  
		 0.5, 0.5, 0.5, 
		 0.5, -0.5, 0.5,  
		 0.5, 0.5, 0.5, 
		 -0.5, -0.5, 0.5, 
		 -0.5, -0.5, 0.5, 
		 0.5, 0.5, 0.5, 
		 -0.5, 0.5, 0.5,  
		 -0.5, -0.5, 0.5, 
		 -0.5, 0.5, 0.5,  
		 -0.5, -0.5, -0.5,
		 -0.5, -0.5, -0.5, 
		 -0.5, 0.5, 0.5,  
		 -0.5, 0.5, -0.5, 
		 -0.5, 0.5, -0.5, 
		 -0.5, 0.5, 0.5,  
		 0.5, 0.5, -0.5,  
		 0.5, 0.5, -0.5,  
		 -0.5, 0.5, 0.5,  
		 0.5, 0.5, 0.5,
		 -0.5, -0.5, -0.5, 
		 0.5, -0.5, -0.5, 
		 -0.5, -0.5, 0.5, 
		 0.5, -0.5, -0.5, 
		 0.5, -0.5, 0.5,  
		 -0.5, -0.5, 0.5, 
	};


	// duplicating verts...
	for(int i=0; i<36*3; i+=3*3)
	{
		glm::vec3 v1( gCubeVerts[i+0], gCubeVerts[i+1], gCubeVerts[i+2] );
		glm::vec3 v2( gCubeVerts[i+3], gCubeVerts[i+4], gCubeVerts[i+5] );
		glm::vec3 v3( gCubeVerts[i+6], gCubeVerts[i+7], gCubeVerts[i+8] );

		glm::vec3 n = glm::cross( (v2-v1), (v3-v1) );
		n = glm::normalize( n );

		dexgel::SVertex vert1; 
		vert1.x = v1.x; 
		vert1.y = v1.y; 
		vert1.z = v1.z; 
		vert1.color = 0xffffff00;
		
		dexgel::SVertex vert2; 
		vert2.x = v1.x + n.x;
		vert2.y = v1.y + n.y;
		vert2.z = v1.z + n.z;
		vert2.color = 0xffffff00;

		dexgel::SVertex vert3; 
		vert3.x = v2.x; 
		vert3.y = v2.y; 
		vert3.z = v2.z; 
		vert3.color = 0xffffff00;

		dexgel::SVertex vert4; 
		vert4.x = v2.x + n.x;
		vert4.y = v2.y + n.y;
		vert4.z = v2.z + n.z;
		vert4.color = 0xffffff00;

		dexgel::SVertex vert5; 
		vert5.x = v3.x; 
		vert5.y = v3.y; 
		vert5.z = v3.z; 
		vert5.color = 0xffffff00;

		dexgel::SVertex vert6; 
		vert6.x = v3.x + n.x;
		vert6.y = v3.y + n.y;
		vert6.z = v3.z + n.z;
		vert6.color = 0xffffff00;

		verts.push_back( vert1 );
		verts.push_back( vert2 );

		verts.push_back( vert3 );
		verts.push_back( vert4 );

		verts.push_back( vert5 );
		verts.push_back( vert6 );
	}

	while( App.IsOpened() )
	{
		App.UpdateMessages();

		if( App.canRender() )
		{
			time = App.getTime();
			dt = time - oldtime;
			oldtime = time;

			rend->begin(); // Begin the scene
			rend->clearColor( 0xff323232, 1.0f );
			rend->enableLighting();
			
			//rend->setLightPos( 0, glm::vec3(px, py, pz) );
			float r = 5.0f;
			float a = 6.28f * float( App.getMouseX() ) /  xres ;
			glm::vec3 light_pos = glm::vec3(sin(a)*r, 0.0f, cos(a)*r ) ;
			{
				int i=0;
				rend->setLightPos(i, light_pos);
				rend->setLightColor(i, 0xffffff, 0xffffff, 0x7f7f7f);
				rend->setLightType(i, dexgel::LIGHT_POINT);
				rend->setLightAttenuation(i, 0.01f, 0.05f, 0.0f );
				rend->setLightRange(i, 100.0f ); //50.0f * float( App.getMouseX() ) /  xres );
				rend->setLightActive(i, true);
			}

			float mouse_speed_x = App.getMouseX() - oldmousx;
			float mouse_speed_y = App.getMouseY() - oldmousy;

			if ( App.mouseDown() )
			{	
				hang -= mouse_speed_x * 1.0f;
				vang -= mouse_speed_y * 1.0f;
			}

			oldmousx = (float)App.getMouseX();
			oldmousy = (float)App.getMouseY();


			glm::vec4 dirvec = (10.0f * dt) * glm::vec4( App.keyDown('A')-App.keyDown('D'), 0.0f,  App.keyDown('S') - App.keyDown('W'), 1.0f );
			glm::mat4 rmx = glm::rotate( glm::mat4(1.0), vang, glm::vec3(1.f, 0.f, 0.f)  );
			glm::mat4 rmy = glm::rotate( glm::mat4(1.0), hang, glm::vec3(0.f, 1.f, 0.f)  );
			glm::mat4 rotmat = rmx * rmy;

			glm::vec3 pos = glm::vec3( px,py,pz);
			mCam = rotmat;
			glm::vec4 newdir = dirvec*rotmat;
			glm::vec3 newpos = pos + glm::vec3( newdir.x, newdir.y, newdir.z );
			px = newpos.x;
			py = newpos.y;
			pz = newpos.z;
			mCam = glm::translate( mCam, newpos );

			rend->setProjMatrix( 60.0f * 3.14f / 180.f, xres/yres, 1.0f, 8192.0f );
			glm::mat4 identity = glm::mat4(1.0);	
			
			glm::mat4 rotX = glm::rotate( identity, 90.0f, glm::vec3(1.f, 0.f, 0.f)  );
			rend->setViewMatrix( (float*)&mCam[0] );

			// Show light pos
			//glm::mat4 mWorld = identity;

			glm::mat4 mWorld = glm::translate( identity, glm::vec3(0.f, 0.f, 0.f) );	
			rend->SetTransform( (float*) (&mWorld[0]) );
			rend->render(mesh);
			rend->renderLine( &verts[0], verts.size() );

			mWorld = glm::translate( identity, light_pos );	
			rend->SetTransform( (float*) (&mWorld[0]) );
			rend->disableLighting();
			rend->render(mesh);

			

			rend->end(); // Begin the scene
		}
		
	}

	return EXIT_SUCCESS;
}